package astoliarskyi.lab2;

import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;

public class SumSin {
	
	private final int threadNumber;
	
	public static void main(String[] args) {
		SumSin sinSum = new SumSin(5);
		int N = 10000;
		double sum = sinSum.calculateSinSum(N);
		System.out.print("Sum = sin(-N) + sin(-N+1) + ... + sin(N-1) + sin(N) = ");
		System.out.println(sum);
	}
	
	public SumSin(int threadNumber){
		this.threadNumber = threadNumber;
	}
	
	public double calculateSinSum(int N){
		int tasksPerThread = (2*N+1) / threadNumber;
		int nextN = -N;
		List<SinSumThread> threadList = new LinkedList<SinSumThread>();
		
		while (nextN <= N){
			int upToN = (nextN + tasksPerThread <= N) 
				? nextN + tasksPerThread 
				: N;
			SinSumThread thread = new SinSumThread(nextN, upToN);
			thread.start();
			threadList.add(thread);
			nextN = upToN + 1;
		}
		
		BigDecimal result = BigDecimal.valueOf(0);
			
		for (SinSumThread thread : threadList) {
			try {
				thread.join();
			} catch (InterruptedException ex) { /* Won't be interrupted */ }
			result.add(thread.getResult());
		}
		
		return result.doubleValue();
	}
	
	private class SinSumThread extends Thread {
		
		private final int fromN;
		private final int toN;
		private BigDecimal result = BigDecimal.valueOf(0);
		
		public SinSumThread(int fromN, int toN){
			this.fromN = fromN;
			this.toN = toN;
		}

		@Override
		public void run() {
			for (int i=fromN; i <= toN; i++){
				result = result.add(BigDecimal.valueOf(Math.sin(i)));
			}
		}
		
		public BigDecimal getResult(){
			return result;
		}
	}

}
